from rest_framework.views import APIView
from rest_framework.permissions import AllowAny
from rest_framework.renderers import JSONRenderer
from django.contrib.auth import authenticate, login, logout
from .serializers import UserSerializer
from .utils import CustomResponse
import jwt
import aiohttp
import json
from django.conf import settings
import asyncio
from django.contrib.auth.models import User
import time
from asgiref.sync import async_to_sync


class RegisterView(APIView):
    """
    用户注册视图类
    处理新用户注册的相关请求，包括用户信息验证和账户创建
    """
    permission_classes = [AllowAny]  # 允许未登录用户访问此接口


    def post(self, request):
        """
        处理POST请求，创建新用户
        参数：
            username: 用户名
            password: 密码
            email: 电子邮箱
        返回：
            成功：201状态码和用户信息
            失败：400状态码和错误信息
        """
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            user = serializer.save()
            return CustomResponse.success(
                data={"username": user.username},
                msg="注册成功",
                status=201
            )
        return CustomResponse.error(msg=serializer.errors)


class LoginView(APIView):
    """
    用户登录视图类
    处理用户登录请求，验证用户身份并生成访问令牌
    """
    permission_classes = [AllowAny]

    def post(self, request):
        """
        处理POST请求，实现用户登录功能
        """
        username = request.data.get('username')
        password = request.data.get('password')
        user = authenticate(username=username, password=password)

        if user:
            login(request, user)
            # 生成JWT token
            token = jwt.encode(
                {'user_id': user.id},
                settings.SECRET_KEY,
                algorithm='HS256'
            )
            return CustomResponse.success(
                data={"username": username},
                msg="登录成功",
                token=token
            )
        return CustomResponse.error(msg="用户名或密码错误", status=401)


class LogoutView(APIView):
    """
    用户登出视图
    处理用户登出请求，清除会话信息
    """

    def post(self, request):
        """
        处理POST请求，实现用户登出功能
        """
        logout(request)
        return CustomResponse.success(msg="登出成功")


class ForgotPasswordView(APIView):
    """
    找回密码视图
    处理密码重置请求
    """
    permission_classes = [AllowAny]

    def post(self, request):
        """
        处理POST请求，实现密码重置功能
        """
        username = request.data.get('username')
        email = request.data.get('email')

        try:
            user = User.objects.get(username=username, email=email)
            user.set_password('123456')  # 重置密码为默认值
            user.save()
            return CustomResponse.success(msg="密码已重置为123456")
        except User.DoesNotExist:
            return CustomResponse.error(msg="用户名或邮箱不正确", status=401)


class DataInteractionView(APIView):
    """
    数据交互视图
    处理与open-digger的数据交互请求
    """

    def post(self, request):
        """
        处理POST请求，实现数据获取功能
        """
        return async_to_sync(self.handle_post)(request)

    async def handle_post(self, request):
        """
        异步处理POST请求
        """
        # 获取请求参数
        platform = request.data.get('platform')
        org = request.data.get('org')
        repo = request.data.get('repo')
        index = request.data.get('index')

        # 验证参数完整性
        if not all([platform, org, repo, index]):
            return CustomResponse.error(msg="缺少必要参数")

        # 构建URL
        url = f"https://oss.x-lab.info/open_digger/{platform}/{org}/{repo}/{index}.json"

        async with aiohttp.ClientSession() as session:
            try:
                async with session.get(url) as response:
                    if response.status == 200:
                        data = await response.json()
                        return CustomResponse.success(data=data)
                    return CustomResponse.error(msg="获取数据失败", status=response.status)
            except aiohttp.ClientError as e:
                return CustomResponse.error(msg="网络错误: " + str(e))
            except Exception as e:
                return CustomResponse.error(msg="发生错误: " + str(e))


class LLMView(APIView):
    """
    大语言模型视图
    处理前端用户请求并与本地部署的Qwen2模型交互
    """

    def post(self, request):
        """
        处理用户的自然语言请求

        前端请求格式：
        {
            "message": "用户的自然语言输入",
            "context": "可选的上下文信息"
        }

        统一返回格式：
        {
            "status": 200,
            "msg": "success",
            "data": {
                "response": "模型的回复内容",
                "processing_time": 123.45
            },
            "token": "NULL"
        }
        """
        # 1. 获取并验证前端输入
        message = request.data.get('message')
        context = request.data.get('context', '')

        if not message:
            return CustomResponse.error(
                msg="消息内容不能为空",
                status=400
            )

        try:
            # 2. 准备Ollama请求数据
            ollama_request = {
                'model': 'qwen2',  # 使用qwen2模型
                'prompt': message,
                'stream': False,
                'context': context,
                'options': {
                    'temperature': 0.7,
                    'top_p': 0.9,
                    'max_tokens': 2000
                }
            }

            # 3. 调用本地Ollama服务
            with aiohttp.ClientSession() as session:
                start_time = time.time()
                with session.post(
                        'http://localhost:11434/api/generate',
                        json=ollama_request,
                        timeout=aiohttp.ClientTimeout(total=30)
                ) as response:
                    if response.status == 200:
                        result = response.json()
                        processing_time = (time.time() - start_time) * 1000

                        # 4. 使用CustomResponse返回结果
                        return CustomResponse.success(
                            data={
                                'response': result.get('response', ''),
                                'processing_time': round(processing_time, 2)
                            },
                            msg="模型响应成功",
                            status=200
                        )

                    # 处理非200响应
                    return CustomResponse.error(
                        msg="模型服务响应失败",
                        status=response.status
                    )

        except aiohttp.ClientError as e:
            # 网络连接错误
            return CustomResponse.error(
                msg="连接模型服务失败",
                status=503
            )
        except asyncio.TimeoutError:
            # 超时错误
            return CustomResponse.error(
                msg="模型响应超时",
                status=504
            )
        except Exception as e:
            # 其他错误
            return CustomResponse.error(
                msg="处理请求时发生错误",
                status=500
            )

    def stream_response(self, response):
        """
        处理流式响应（如果需要stream模式）
        """
        for line in response.content:
            if line:
                try:
                    yield json.loads(line)
                except json.JSONDecodeError:
                    continue

